﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Daybreak.Core.Rendering.Pipeline
{
    /// <summary>
    /// Standard semantic and annotation storage
    /// </summary>
	public static class SasStorage
	{
		static Dictionary<string, SasSemantic> semNameToEnumMap;
		static Dictionary<string, SasAnnotation> annNameToEnumMap;

		static SasStorage()
		{
			semNameToEnumMap = new Dictionary<string, SasSemantic>();
			annNameToEnumMap = new Dictionary<string, SasAnnotation>();

			SasSemantic[] semValueArr = (SasSemantic[])Enum.GetValues(typeof(SasSemantic));
			SasAnnotation[] annValueArr = (SasAnnotation[])Enum.GetValues(typeof(SasAnnotation));

			for (int i = 0; i < semValueArr.Length; i++)
			{
				SasSemantic sem = semValueArr[i];

				if (sem == SasSemantic._unknown)
					continue;

				semNameToEnumMap.Add(sem.ToString().ToLowerInvariant(), sem);
			}

			for (int i = 0; i < annValueArr.Length; i++)
			{
				SasAnnotation ann = annValueArr[i];

				if (ann == SasAnnotation._unknown)
					continue;

				annNameToEnumMap.Add(ann.ToString().ToLowerInvariant(), ann);
			}
		}

		public static SasSemantic GetKnownSemantic(string semantic)
		{
            if (string.IsNullOrEmpty(semantic))
                return SasSemantic._unknown;

			SasSemantic sem = SasSemantic._unknown;

			if (semNameToEnumMap.TryGetValue(semantic.ToLowerInvariant(), out sem))
				return sem;

			return SasSemantic._unknown;
		}

		public static SasAnnotation GetKnownAnnotation(string annotation)
		{
			SasAnnotation ann = SasAnnotation._unknown;

			if (annNameToEnumMap.TryGetValue(annotation.ToLowerInvariant(), out ann))
				return ann;

			return SasAnnotation._unknown;
		}

	}

	/// <summary>
	/// The following lists known semantics from the Microsoft and NVidia specifications. But some of them 
	/// supported by FxComposer only
	/// </summary>
	/// <remarks>All semantics and annotations are case insensitive</remarks>
	public enum SasSemantic : int
	{
		/// <summary>
		/// Color value to be used as the diffuse color. The fourth channel represents diffuse alpha.
		/// [DataType: float4,float3,texture]
		/// </summary>
		diffuse,

		/// <summary>
		/// Color value to be used as the specular color. The fourth channel represents specular alpha.
		/// [DataType: float4,float3,texture]
		/// </summary>
		specular,

		/// <summary>
		/// Color value to be used as the ambient color. The fourth channel represents ambient alpha.
		/// [DataType: float4,float3,texture]
		/// </summary>
		ambient,

		/// <summary>
		/// Power to use for the specular exponent.
		/// [DataType: float,float3,float4]
		/// </summary>
		specularpower,

		/// <summary>
		/// Color value to be used as the emissive color. The fourth channel represents emissive alpha.
		/// [DataType: float4,float3,texture]
		/// </summary>
		emissive,

		/// <summary>
		/// Normal for the element or texture
		/// [DataType: texture]
		/// </summary>
		normal,

		/// <summary>
		/// Height for the element when using bump mapping.
		/// [DataType: texture]
		/// </summary>
		height,

		/// <summary>
		/// A refraction map that give the coefficents to determine the norma for an environment map lookup
		/// [DataType: texture]
		/// </summary>
		refraction,

		/// <summary>
		/// Opacity of the object.
		/// [DataType: texture]
		/// </summary>
		opacity,

		/// <summary>
		/// An environment map.
		/// [DataType: texture]
		/// </summary>
		environment,

		/// <summary>
		/// An environment normal map.
		/// [DataType: texture]
		/// </summary>
		environmentnormal,

		/// <summary>
		/// A fresnel factor.
		/// [DataType: float4]
		/// </summary>
		fresnel,

		/// <summary>
		/// world matrix.
		/// [DataType: matrix]
		/// </summary>
		world,

		/// <summary>
		/// world-inverse matrix.
		/// [DataType: matrix]
		/// </summary>
		worldinverse,

		/// <summary>
		/// world-inverse-transpose matrix.
		/// [DataType: matrix]
		/// </summary>
		worldinversetranspose,

		/// <summary>
		/// world-view matrix.
		/// [DataType: matrix]
		/// </summary>
		worldview,

		/// <summary>
		/// world-view-inverse matrix.
		/// [DataType: matrix]
		/// </summary>
		worldviewinverse,

		/// <summary>
		/// world-view-inverse-transpose matrix.
		/// [DataType: matrix]
		/// </summary>
		worldviewinversetranspose,

		/// <summary>
		/// world-view-projection matrix.
		/// [DataType: matrix]
		/// </summary>
		worldviewprojection,

		/// <summary>
		/// world-view-projection-inverse matrix.
		/// [DataType: matrix]
		/// </summary>
		worldviewprojectioninverse,

		/// <summary>
		/// world-view-projection-inverse-transpose matrix.
		/// [DataType: matrix]
		/// </summary>
		worldviewprojectioninversetranspose,

		/// <summary>
		/// view matrix.
		/// [DataType: matrix]
		/// </summary>
		view,

		/// <summary>
		/// view-projection matrix.
		/// [DataType: matrix]
		/// </summary>
		viewprojection,

		/// <summary>
		/// view-inverse matrix.
		/// [DataType: matrix]
		/// </summary>
		viewinverse,

		/// <summary>
		/// view-inverse-transpose matrix.
		/// [DataType: matrix]
		/// </summary>
		viewinversetranspose,

		/// <summary>
		/// view-projection-inverse matrix.
		/// [DataType: matrix]
		/// </summary>
		viewprojectioninverse,

		/// <summary>
		/// view-projection-inverse-transpose matrix.
		/// [DataType: matrix]
		/// </summary>
		viewprojectioninversetranspose,

		/// <summary>
		/// Size of the viewport in pixels
		/// [DataType: float2]
		/// </summary>
		viewportpixelsize,

		/// <summary>
		/// projection matrix.
		/// [DataType: matrix]
		/// </summary>
		projection,

		/// <summary>
		/// projection-inverse matrix.
		/// [DataType: matrix]
		/// </summary>
		projectioninverse,

		/// <summary>
		/// projection-inverse-transpose matrix.
		/// [DataType: matrix]
		/// </summary>
		projectioninversetranspose,

		/// <summary>
		/// A texture coordinate transform matrix.
		/// [DataType: matrix]
		/// </summary>
		texturematrix,

		/// <summary>
		/// The current time (see units annotation for scale).
		/// [DataType: float]
		/// </summary>
		time,

		/// <summary>
		/// The last frame time (see units annotation for scale).
		/// [DataType: float]
		/// </summary>
		lasttime,

		/// <summary>
		/// The time between adjacent frames (see units annotation for scale).
		/// [DataType: float]
		/// </summary>
		elapsedtime,

		/// <summary>
		/// Defines the modeling proportions to the current unit/space.
		/// [DataType: float]
		/// </summary>
		unitsscale,

		/// <summary>
		/// Standards version and global annotations
		/// [DataType: float]
		/// </summary>
		standardsglobal,

		/// <summary>
		/// A position vector.
		/// [DataType: float3]
		/// </summary>
		position,

		/// <summary>
		/// A direction vector.
		/// [DataType: float3]
		/// </summary>
		direction,

		/// <summary>
		/// Light attenuation.
		/// [DataType: float3]
		/// </summary>
		attenuation,

		/// <summary>
		/// Defines the texture as the render target of a pass in the effect.
		/// [DataType: texture]
		/// </summary>
		rendercolortarget,

		/// <summary>
		/// Defines the texture as the render target of a pass in the effect.
		/// [DataType: texture]
		/// </summary>
		renderdepthstenciltarget,

		/// <summary>
		/// Bounding box center.
		/// [DataType: float3][NotSupported]
		/// </summary>
		boundingcenter,

		/// <summary>
		/// Bounding sphere radius.
		/// [DataType: float,float3][NotSupported]
		/// </summary>
		boundingsphereradius,

		/// <summary>
		/// Bounding box size.
		/// [DataType: float3][NotSupported]
		/// </summary>
		boundingboxsize,

		/// <summary>
		/// Bounding minimum for x, y, z
		/// [DataType: float3][NotSupported]
		/// </summary>
		boundingboxmin,

		/// <summary>
		/// Bounding maximum for x, y, z
		/// [DataType: float3][NotSupported]
		/// </summary>
		boundingboxmax,

		/// <summary>
		/// Light projection matrix.
		/// [DataType: matrix][NotSupported]
		/// </summary>
		lightprojection,

		/// <summary>
		/// A random value between 0->1
		/// [DataType: float,float2,float3,float4,int][NotSupported]
		/// </summary>
		random,

		/// <summary>
		/// near distance, far distance, width angle(radians), height angle(radians)
		/// [DataType: float4][NotSupported]
		/// </summary>
		viewportclipping,

		/// <summary>
		/// world-view-transpose matrix.
		/// [DataType: matrix][FXComposerOnly]
		/// </summary>
		worldviewtranspose,

		/// <summary>
		/// view-projection-transpose matrix.
		/// [DataType: matrix][FXComposerOnly]
		/// </summary>
		viewprojectiontranspose,

		/// <summary>
		/// world-transpose matrix.
		/// [DataType: matrix][FXComposerOnly]
		/// </summary>
		worldtranspose,

		/// <summary>
		/// view-transpose matrix.
		/// [DataType: matrix][FXComposerOnly]
		/// </summary>
		viewtranspose,

		/// <summary>
		/// Light cone umbra
		/// [DataType: float][FXComposerOnly]
		/// </summary>
		lightumbra,

		/// <summary>
		/// Light cone penumbra
		/// [DataType: float][FXComposerOnly]
		/// </summary>
		lightpenumbra,

		/// <summary>
		/// Light effective range
		/// [DataType: float][FXComposerOnly]
		/// </summary>
		lightrange,

		/// <summary>
		/// Spotlight cone falloff between umbra and penumbra
		/// [DataType: float4][FXComposerOnly]
		/// </summary>
		lightfalloff,

		/// <summary>
		/// The mouse position on screen (x,y,time)
		/// [DataType: float3][FXComposerOnly]
		/// </summary>
		mouseposition,

		/// <summary>
		/// The left mouse down state, and its position at that time ( x, y, isdown, timedown)
		/// [DataType: float4][FXComposerOnly]
		/// </summary>
		leftmousedown,

		/// <summary>
		/// The right mouse down state, and its position at that time ( x, y, isdown, timedown)
		/// [DataType: float4][FXComposerOnly]
		/// </summary>
		rightmousedown,

		/// <summary>
		/// Viewer position in world space (replaced by position with space=view annotation).
		/// [DataType: float3][FXComposerOnly]
		/// </summary>
		cameraposition,

		/// <summary>
		/// A pulsed boolean, reset on window resize or from the FX Composer user interface.
		/// [DataType: bool][FXComposerOnly]
		/// </summary>
		fxcomposer_resetpulse,
        
        /// <summary>
		/// Indicates FXComposer non compliant semantic
		/// </summary>
		none,

		_unknown, // this one should be the last one

	}

	/// <summary>
	/// The following lists known annotations from the Microsoft specification.
	/// </summary>
	/// <remarks>All semantics and annotations are case insensitive</remarks>
	public enum SasAnnotation
	{
		/// <summary>
		/// This is type is associated with a frustum
		/// [DataType: matrix]
		/// </summary>
		frustum,

		/// <summary>
		/// This is a string that describes variable, i.e. a pretty name used for labeling an ui dialog
		/// [DataType: string]
		/// </summary>
		uiname,

		/// <summary>
		/// This is the string for helpful information that is displayed to a user in a tool.
		/// [DataType: string][NotSupported]
		/// </summary>
		uihelp,

		/// <summary>
		/// Described the widget to be used to edit the value.
		/// [DataType: string]
		/// </summary>
		uiwidget,

		/// <summary>
		/// Defines the minimum value that the variable should be set to.
		/// [DataType: int,float,float2,float3,float4]
		/// </summary>
		uimin,

		/// <summary>
		/// Defines the maximum value that the variable should be set to.
		/// [DataType: int,float,float2,float3,float4]
		/// </summary>
		uimax,

		/// <summary>
		/// Defines the incremental steps that should be used when incrementing or decrementing this value.
		/// [DataType: int,float,float2,float3,float4]
		/// </summary>
		uistep,

		/// <summary>
		/// The power applied to each UIStep
		/// [DataType: int,float,float2,float3,float4][NotSupported]
		/// </summary>
		uisteppower,

		/// <summary>
		/// What is the data used for, i.e. What Coordinate system this variable is intended to be used in.
		/// [DataType: string]
		/// </summary>
		space,

		/// <summary>
		/// How the variable is intended to be used.
		/// [DataType: string]
		/// </summary>
		usage,

		/// <summary>
		/// Describes the units for the value. i.e. for Time may be seconds. Distance may be meters.
		/// [DataType: string]
		/// </summary>
		units,

		/// <summary>
		/// Specifies the value should be treated as a normalized value.
		/// [DataType: bool]
		/// </summary>
		normalize,

		/// <summary>
		/// A script entry point, in a technique, pass, or a standards global parameter, which will define the drawing instructions.
		/// [DataType: string]
		/// </summary>
		script,

		/// <summary>
		/// Classification of scene, object or both.
		/// [DataType: string]
		/// </summary>
		scriptclass,

		/// <summary>
		/// Ordering of preprocess, postprocess, or standard.
		/// [DataType: string]
		/// </summary>
		scriptorder,

		/// <summary>
		/// What will be written into the rendertarget.
		/// [DataType: string]
		/// </summary>
		scriptoutput,

		/// <summary>
		/// A set of 3 bools indicating that state needs to be saved - i.e. the flags for ID3DXEffect::Begin.
		/// [DataType: string]
		/// </summary>
		scriptsavestate,

		/// <summary>
		/// compiler target for the HLSL compiler.
		/// [DataType: string][NotSupported]
		/// </summary>
		targetps,

		/// <summary>
		/// compiler target for the HLSL compiler.
		/// [DataType: string][NotSupported]
		/// </summary>
		targetvs,

		/// <summary>
		/// Specifies what the object of the semantic is.
		/// [DataType: string]
		/// </summary>
		Object,

		/// <summary>
		/// The type of attenuation used.
		/// [DataType: string]
		/// </summary>
		attenuationtype,

		/// <summary>
		/// A string that names the resource name to be used for interface objects, i.e. filename for a texture. 
		/// [DataType: string]
		/// </summary>
		resourcename,

		/// <summary>
		/// Defines that the width/height are a ratio of the viewport dimensions
		/// [DataType: float2]
		/// </summary>
		viewportratio,

		/// <summary>
		/// Defines the suggested width for a texture object.
		/// [DataType: int]
		/// </summary>
		width,

		/// <summary>
		/// Defines the suggested width/height/depth for a texture object.
		/// [DataType: float,float2,float3]
		/// </summary>
		dimensions,

		/// <summary>
		/// Defines the suggested height for a texture object.
		/// [DataType: int]
		/// </summary>
		height,

		/// <summary>
		/// Defines the suggested depth for a texture object.
		/// [DataType: int]
		/// </summary>
		depth,

		/// <summary>
		/// Number of mip levels requested.
		/// [DataType: int]
		/// </summary>
		miplevels,

		/// <summary>
		/// D3DFormat of the texture.
		/// [DataType: string]
		/// </summary>
		format,

		/// <summary>
		/// Type of the resource - 2d,3d, cube, etc.
		/// [DataType: string]
		/// </summary>
		resourcetype,

		/// <summary>
		/// A function to generate this object with
		/// [DataType: string]
		/// </summary>
		function,

		/// <summary>
		/// A way to give a pass/technique a semantic, by providing an annotation. 
		/// Future DX versions will support native semantics on passes/effects.
		/// [DataType: string][NotSupported]
		/// </summary>
		semantic,

		/// <summary>
		/// The file filter presented in the properties panel
		/// [DataType: string][FXComposerOnly]
		/// </summary>
		uifilefilter,

		_unknown, // this one should be the last one
	}

}
